package br.ufrj.dcc.ad.event;

import java.util.ArrayList;
import java.util.List;

import br.ufrj.dcc.ad.args.ParametrosSimulacao;
import br.ufrj.dcc.ad.enums.ServerType;
import br.ufrj.dcc.ad.systems.Cliente;
import br.ufrj.dcc.ad.systems.Servidor;

public class InterruptEvent extends Event {
	
	/**
	 * Gera o evento de interrupção ao cliente no servidor.
	 * @param cliente O cliente que está interrompendo por ter maior prioridade.
	 * @param servidor O servidor que sofrerá a interrupção.
	 * @param tempoOcorrencia O tempo de ocorrência da interrupção.
	 */
	public InterruptEvent(Cliente gerador, Servidor servidor, double tempoOcorrencia) {
		super(gerador,servidor,tempoOcorrencia);
	}

	@Override
	public List<Event> executaAcao() {
		List<Event> eventosIvocacao = new ArrayList<Event>(); 
		Cliente clienteServidor = servidor.getConsumidor();
		
		//O tempo de consumo do cliente do servidor já é atualizado pelo seu próprio ServerAtendmentEvent, 
		//quando este detecta que há um proximo evento entre o seu tempo de consumo.
		
		//Se o evento não foi todo consumido realize uma reentrada imediata na fila de origem.
		if(clienteServidor.getTempoConsumoRestante() > 0.0){
			if(ParametrosSimulacao.getTipoServidor() == ServerType.NCONTINUO){
				clienteServidor.addTempoVaoServidor(clienteServidor.getTipoCliente(),tempoOcorrencia - clienteServidor.getTempoUltimaEntradaServidor());
			}
			clienteServidor.setTempoUltimaEntradaServidor(null);
			eventosIvocacao.add(new ReenterEvent(clienteServidor, servidor, tempoOcorrencia));
		}
		
		//O cliente que gerou a interrupção entra imediatamente no servidor.
		ServerAtendmentEvent serverAtendmentEvent = new ServerAtendmentEvent(gerador, servidor, tempoOcorrencia);
		eventosIvocacao.add(serverAtendmentEvent);
		//Há no mínimo um evento de consumo agendado para clientes com menor prioridade que este, 
		//estes devem ser cancelados.(Um deles é o evento do cliente que estava no servidor antes da interrupção).
		eventosIvocacao.add(new CancelScheduledAtendmentsEvent(gerador,serverAtendmentEvent,servidor,tempoOcorrencia));
		return eventosIvocacao;
	}
}
